#include "interval_tests.hpp"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <sstream>

using namespace utils;

typedef boost::mpl::list< interval_test_fixture< int> > test_types;

namespace 
{

BOOST_AUTO_TEST_CASE_TEMPLATE( testInsersectWithLarger, TestFixture, test_types)
{
	//  0  1    3    5    7 8
	//     |====|    |====|
	//  |^^^^^^^^^^^^^^^^^^^|
	TestFixture fixture;
	typename TestFixture::interval_set_type interval;
	fixture.prepare_first_interval( interval);
	fixture.prepare_second_interval( interval);
	// Now, we have two intervals.
	interval.intersect( fixture.values_[0], fixture.values_[8]);
	BOOST_REQUIRE_EQUAL( 2, interval.size());
	CHECK_INTERVAL( fixture.values_[1], fixture.values_[3], *interval.begin());
	CHECK_INTERVAL( fixture.values_[5], fixture.values_[7], *(++interval.begin()));
}

// --------------------------------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE_TEMPLATE( testInsersectWithFixed, TestFixture, test_types)
{
	//  1    3    5    7
	//  |====|    |====|
	//  |^^^^^^^^^^^^^^|
	TestFixture fixture;
	typename TestFixture::interval_set_type interval;
	fixture.prepare_first_interval( interval);
	fixture.prepare_second_interval( interval);
	// Now, we have two intervals.
	interval.intersect( fixture.values_[0], fixture.values_[7]);
	BOOST_REQUIRE_EQUAL( 2, interval.size());
	CHECK_INTERVAL( fixture.values_[1], fixture.values_[3], *interval.begin());
	CHECK_INTERVAL( fixture.values_[5], fixture.values_[7], *(++interval.begin()));
}

// --------------------------------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE_TEMPLATE( testInsersectWithSmaller, TestFixture, test_types)
{
	//  1  2 3    5  6 7
	//  |====|    |====|
	//     |^^^^^^^^^|
	TestFixture fixture;
	typename TestFixture::interval_set_type interval;
	fixture.prepare_first_interval( interval);
	fixture.prepare_second_interval( interval);
	// Now, we have two intervals.
	interval.intersect( fixture.values_[2], fixture.values_[6]);
	BOOST_REQUIRE_EQUAL( 2, interval.size());
	CHECK_INTERVAL( fixture.values_[2], fixture.values_[3], *interval.begin());
	CHECK_INTERVAL( fixture.values_[5], fixture.values_[6], *(++interval.begin()));
}


// --------------------------------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE_TEMPLATE( testInsersectElimination, TestFixture, test_types)
{
	//  1  2 3  4 5    7
	//  |====|    |====|
	//     |^^^^|
	TestFixture fixture;
	typename TestFixture::interval_set_type interval;
	fixture.prepare_first_interval( interval);
	fixture.prepare_second_interval( interval);
	// Now, we have two intervals.
	interval.intersect( fixture.values_[2], fixture.values_[4]);
	BOOST_REQUIRE_EQUAL( 1, interval.size());
	CHECK_INTERVAL( fixture.values_[2], fixture.values_[3], *interval.begin());
}


// --------------------------------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE_TEMPLATE( testInsersectCompleteElimination, TestFixture, test_types)
{
	//  1    3    5    7
	//  |====|    |====|
	//       |^^^^|
	TestFixture fixture;
	typename TestFixture::interval_set_type interval;
	fixture.prepare_first_interval( interval);
	fixture.prepare_second_interval( interval);
	// Now, we have two intervals.
	interval.intersect( fixture.values_[3], fixture.values_[5]);
	BOOST_REQUIRE_EQUAL( 0, interval.size());
}

} // namespace
